﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Krist_em_up;
using Krist_em_up.Components;
using Map_Editor.Effects;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Krist_em_up.Level;
using System.Windows.Forms;
using System.ComponentModel;
using Krist_em_up.Plateforms;

namespace Map_Editor
{
    public class Editor : Game
    {

        GraphicsDeviceManager graphics;

        protected Clavier kb;
        protected bool[,] plateforms;
        protected MouseState mouse;

        protected Texture2D texture;

        protected Sidebar sidebar;

        protected Map map;

        public Map Map
        {
            get { return map; }
        }

        public const int HEIGHT = 30;
        public const int WIDTH = 30;

        public const int WINDOW_HEIGHT = 600;
        public const int WINDOW_WIDTH = 800;

        protected TimeSpan MoveTimer;

        protected Vector2 origin;

        protected Viewport editorViewport, sidebarViewport, defaultViewport;

        SaveFileDialog sfd;

        OpenFileDialog ofd, imgPicker;

        protected ClickEffect effect;
        public ClickEffect Effect
        {
            get
            {
                return effect;
            }
            set
            {
                effect = value;
            }
        }

        protected Rectangle rectangle;

        public Editor() : base()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferHeight = WINDOW_HEIGHT;
            graphics.PreferredBackBufferWidth = WINDOW_WIDTH;
            Content.RootDirectory = "Content";

            IsMouseVisible = true;
            rectangle = new Rectangle(0, 0, 8 * WINDOW_WIDTH / 10, WINDOW_HEIGHT);

            MoveTimer = TimeSpan.Zero;
        }

        protected override void Initialize()
        {
            kb = new Clavier(this);
            sidebar = new Sidebar(this);
            Components.Add(kb);
            Components.Add(sidebar);
            plateforms = new bool[50, 50];

            sfd = new SaveFileDialog();
            sfd.FileOk += new CancelEventHandler(sfd_FileOK);

            ofd = new OpenFileDialog();
            ofd.FileOk += new CancelEventHandler(ofd_FileOk);

            imgPicker = new OpenFileDialog();
            imgPicker.FileOk += new CancelEventHandler(imgPicker_FileOk);
            imgPicker.Filter = "Image Files(*.BMP;*.JPG;*.PNG)|*.PNG;*.JPG;*.GIF";

            defaultViewport = GraphicsDevice.Viewport;

            editorViewport = GraphicsDevice.Viewport;
            editorViewport.Width = 4 * editorViewport.Width / 5;

            sidebarViewport = GraphicsDevice.Viewport;
            sidebarViewport.Width = defaultViewport.Width / 5;
            sidebarViewport.X = editorViewport.Width;

            
            base.Initialize();

        }

        private void sfd_FileOK(object sender, CancelEventArgs e)
        {
            map.SaveToFile(((SaveFileDialog) sender).FileName);
        }

        private void ofd_FileOk(object sender, CancelEventArgs e)
        {
            map = Map.LoadFromFile(((OpenFileDialog) sender).FileName, graphics.GraphicsDevice);
        }

        private void imgPicker_FileOk(object sender, CancelEventArgs e)
        {
            //Wait...
            OpenFileDialog o = (OpenFileDialog) sender;

            map.Plateform = Texture2D.FromFile(GraphicsDevice, o.FileName);
        }
        
        protected override void LoadContent()
        {
            texture = Content.Load<Texture2D>("void");
            map = new Map();
            map.Plateform = Content.Load<Texture2D>("Block");
            
        }
        protected override void Update(GameTime gametime)
        {
            mouse = Mouse.GetState();
            int x = (int)mouse.X / WIDTH;
            int y = (int)mouse.Y / HEIGHT;
            if (effect != null && rectangle.Contains(mouse.X, mouse.Y) && IsInBounds<bool>(plateforms, x, y))
            {
                if (mouse.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    effect.LeftApply(map, new Vector2(x, y) + origin);
                }
                else if (mouse.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                {
                    effect.RightApply(map, new Vector2(x, y) + origin);
                }
            }
            
            KeyboardState kb = Keyboard.GetState();
            if (kb.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.S))
            {
                DialogResult result = sfd.ShowDialog();                
            }
            else if (kb.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.O))
            {
                DialogResult result = ofd.ShowDialog();
            }
            else if (kb.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.I))
            {
                DialogResult result = imgPicker.ShowDialog();
            }
            if (MoveTimer <= TimeSpan.Zero)
            {
                if (kb.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Left))
                {
                    origin.X--;
                }
                else if(kb.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Right))
                {
                    origin.X++;
                }
                origin.X = MathHelper.Clamp(origin.X, 0, map.Plateforms.GetLength(0) - editorViewport.Width/WIDTH);
                MoveTimer = new TimeSpan(0, 0, 0, 0, 250);
            }
            else
            {
                MoveTimer -= gametime.ElapsedGameTime;
            }
            base.Update(gametime);
        }

        protected override void Draw(GameTime gametime)
        {
            SpriteBatch spritebatch = new SpriteBatch(GraphicsDevice);
            spritebatch.Begin();

            GraphicsDevice.Viewport = editorViewport;
            GraphicsDevice.Clear(Color.Black);

            for (int x = 0; x < map.Plateforms.GetLength(0); x++)
            {
                for (int y = 0; y < map.Plateforms.GetLength(1); y++)
                {                   
                    if(map.Plateforms[x, y].Collision == TileCollision.Impassable)
                    {
                        spritebatch.Draw(map.Plateform, new Rectangle((x - (int)origin.X) * WIDTH, (y - (int)origin.Y) * HEIGHT, WIDTH, HEIGHT), Color.White);
                    }
                }
            }
            spritebatch.Draw(Content.Load<Texture2D>("KrisboolIdle"), new Rectangle((int)(map.Spawn.X - origin.X) * WIDTH,
                (int)(map.Spawn.Y - origin.Y) * HEIGHT, WIDTH, HEIGHT), Color.White);

            spritebatch.Draw(Content.Load<Texture2D>("flecheD"), new Rectangle((int)(map.endOfLevel.X - origin.X) * WIDTH,
                (int)(map.endOfLevel.Y - origin.Y) * HEIGHT, WIDTH, HEIGHT), Color.White);

            foreach (Vector2 pos in map.ennemiesSpawnPositions)
            {
                spritebatch.Draw(Content.Load<Texture2D>("Kris"), new Rectangle((int)(pos.X - origin.X)* WIDTH,
                    (int)(pos.Y - origin.Y) * HEIGHT, WIDTH, HEIGHT), Color.White);
            }
            spritebatch.End();

            //GraphicsDevice.Viewport = defaultViewport;
            base.Draw(gametime);
        }

        public static bool IsInBounds<T>(T[,] array, int x, int y)
        {
            return (x >= 0 && y >= 0 && x < array.GetLength(0) && y < array.GetLength(1));
        }

        public void ViewportSidebar()
        {
            GraphicsDevice.Viewport = sidebarViewport;
            GraphicsDevice.Clear(Color.Khaki);
        }
    }
}
